/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package computing;

import com.jme3.asset.AssetManager;
import com.jme3.cinematic.MotionPath;
import com.jme3.cinematic.MotionPathListener;
import com.jme3.cinematic.events.MotionTrack;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Sphere;
import data.Grid3d;
import data.Vector3i;
import debug.DebugPoint;
import debug.DebugPrinter;
import exception.WaypointsNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author oxplay
 */
public class EasyFind {

    public static final String NODETYPE_CHARACTER = "character";
    public static final String NODETYPE_OBJECT = "object";
    public static final String NODETYPE_CLIMBABLE = "climbable";
    private final static Logger logger = Logger.getLogger(EasyFind.class.getName());
    private Node rootNode;
    private AssetManager assetManager;
    public Grid3d grid;
    public int seekCatchPointRange = 1;
    public Vector3i calculationsOffset;

    public EasyFind(AssetManager assetManager, Node rootNode, int seekCatchPointRange, Vector3i calculationsOffset) {
        this.assetManager = assetManager;
        this.rootNode = rootNode;
        this.seekCatchPointRange = seekCatchPointRange;
        this.grid = new Grid3d();
        this.calculationsOffset = calculationsOffset;
        logger.setLevel(Level.WARNING);
    }

    public class DefaultDebugPoint extends DebugPoint {

        private Sphere sphere = new Sphere(8, 8, 0.5f);
        private Geometry geom = null;

        @Override
        public void make(Vector3f vect, pointfinder.PointEntity point) {
            geom = new Geometry("sphere" + vect, sphere);
            Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
            mat.setColor("Color", ColorRGBA.Orange);
            geom.setMaterial(mat);
            rootNode.attachChild(geom);
            geom.setLocalTranslation(vect.x, vect.y, vect.z);
        }

        @Override
        public void remove() {
            geom.removeFromParent();
        }
    };

    public void initGridFromWorld(Node node) {
        grid.examineSpatial(node);
    }

    public void clearGrid() {
        grid.containers.clear();
    }
    private DebugPrinter debugPrinter = new DebugPrinter() {

        @Override
        public DebugPoint getNewDebugPoint() {
            return new DefaultDebugPoint();
        }
    };

    public void setDebugPrinter(DebugPrinter debugPrinter) {
        this.debugPrinter = debugPrinter;
    }

    public void setGrid3d(Grid3d grid) {
        this.grid = grid.clone();
    }

    public String printWaypoints(ArrayList<Vector3f> waypoints) {
        String waypointText = "";
        if (waypoints != null) {
            for (Iterator<Vector3f> it = waypoints.iterator(); it.hasNext();) {
                Vector3f vector3 = it.next();
                waypointText += "waypoint: [" + vector3.x + "," + vector3.y + "," + vector3.z + "]";
            }
        }
        return waypointText;
    }

    public ArrayList<Vector3f> getWaypoints(Vector3f from, Vector3f to, boolean useSimulation, boolean useCalculations) throws WaypointsNotFoundException {
        MakeWaypointsProgressing makeWaypointsProgressing = new MakeWaypointsProgressing(this, from, to, useSimulation, useCalculations, -1);
        while (!makeWaypointsProgressing.isDone()) {
            logger.log(Level.INFO, "[[making steps]]");
            makeWaypointsProgressing.update();
        }
        return makeWaypointsProgressing.getWaypoints();
    }

    public MotionPath getWaypointsAsMotionPath(Vector3f from, Vector3f to, boolean useSimulation, boolean useCalculations) throws WaypointsNotFoundException {
        ArrayList<Vector3f> waypoints = getWaypoints(from, to, useSimulation, useCalculations);
        MotionPath path = new MotionPath();
        for (Iterator<Vector3f> it = waypoints.iterator(); it.hasNext();) {
            Vector3f vector3f = it.next();
            path.addWayPoint(vector3f);
        }
        return path;
    }

    public void showGridNearVector(Vector3f vect, int size) {
        Vector3i vector3i = new Vector3i(vect);
        logger.log(Level.INFO, "showGridNearVector: vect: {0} -> {1} size: {2}", new Object[]{vect, vector3i, size});
        ArrayList<Vector3i> vectors = grid.getPointsNearVector(vector3i, size);
        showGrid(vectors);
    }

    public void showGridSector(Vector3i from, Vector3i to) {
        Set<Vector3i> vectors = grid.getMoveableVectors(from, to);
        showGrid(vectors);
    }

    public void showGridWaypoints(ArrayList<Vector3f> waypoints) {
        debugPrinter.clear();
        for (Iterator<Vector3f> it = waypoints.iterator(); it.hasNext();) {
            Vector3f vector = it.next();
            debugPrinter.printVector(vector, null);
        }
    }

    public void showGrid(Set<Vector3i> vectors) {
        debugPrinter.clear();
        logger.log(Level.INFO, "showGrid: vectors: {0}", vectors);
        for (Iterator<Vector3i> it = vectors.iterator(); it.hasNext();) {
            Vector3i vector = it.next();
            debugPrinter.printVector(vector.getVector3f(), null);
        }
    }

    public void showGrid(ArrayList<Vector3i> vectors) {
        debugPrinter.clear();
        logger.log(Level.INFO, "showGrid: vectors: {0}", vectors);
        for (Iterator<Vector3i> it = vectors.iterator(); it.hasNext();) {
            Vector3i vector = it.next();
            debugPrinter.printVector(vector.getVector3f(), null);
        }
    }
}
